#include <iostream>
#include <string>
#include <math.h>
#include <fstream>
#include <algorithm>
#include <stdio.h>
#include <boost/filesystem/path.hpp>
#include <boost/program_options.hpp>
#include <boost/regex.hpp>
#include "get_arg.h"



// link with -lboost_filesystem-gcc -lboost_program_options-gcc
// program_options_helper.cpp
//-lboost_filesystem-gcc-d
//-L/usr/local/lib





// my functions
#include <print_error.h>
#include <program_options_helper.h>
#include <stlhelper.h>
#define DEBUG_LEVEL 6
#include <debug_func.h>
#include <blast_results.h>
#include <codeml_results.h>

using std::string;
using std::cerr;
using std::string;
using std::ofstream;
using std::ifstream;
using std::cerr;
using std::cout;
using std::max;
using boost::filesystem::path;
using namespace program_options_helper;
namespace po = boost::program_options_lg;

//_______________________________________________________________________________________

//		process_command_line_options

//				from command line
//				Created [9/13/2001]

//_______________________________________________________________________________________
bool process_command_line_options(int argc, char* argv[], t_program_args& args)
{

	//
	// checked mandatory arguments
	//
	po::options_description mandatory_args("Mandatory Arguments");
	mandatory_args.add_options()
	("file1in,x", 			po::value<string>(&args.file_input1)->set_name("FILE"),
								"First list of identifiers.")
	("file2in,y", 			po::value<string>(&args.file_input2)->set_name("FILE"),
								 "Second list of identifiers.");

	po::options_description hidden_args("Hidden Arguments");
	hidden_args.add_options()
	("debug", 					"Set all parameters for debug.\n");

	args.optional_args.add_options()
	("counts,c", 		po::value<string>(&args.file_summary)
									->set_name("FILE"),
								"Repeats information shown with --verbose.")
	("file1_only,i",	po::value<string>(&args.file_1)
									->set_name("FILE"),
								"File to hold identifiers ONLY found in input_file1.")
	("file2_only,j",	po::value<string>(&args.file_2)
									->set_name("FILE"),
								"File to hold identifiers ONLY found in input_file2.")
	("shared_ids,s",	po::value<string>(&args.file_shared)
									->set_name("FILE"),
								"File to hold identifiers found in BOTH input files.")
	("merged_ids,m",	po::value<string>(&args.file_merged)
									->set_name("FILE"),
								"File to hold identifiers found in EITHER input files.")
	("regex,r", 		po::value<string>(&args.regex)
									->set_name("REGEX")
									->default_value("(.*)"),
								"Perl Regular expression to extract patterns.")
	("ignore_case,I",	po::bool_switch(&args.ignore_case),
									"ignore case distinctions in identifiers.");

	po::options_description advanced_args("Arguments for Advanced Users");
	advanced_args.add_options()
	("to_regex,T", 		po::value<string>(&args.to_regex)
									->set_name("REGEX")
									->default_value("\\1"),
								"Transforms the matching patterns. Defaults to matching "
								"either the first matching subexpression within "
								"parentheses or the entire match.")
						;
	
	


	args.add_std_options();
	po::options_description all_args("");
	all_args.add(mandatory_args).add(args.optional_args).add(hidden_args).add(advanced_args);

	// parse command line
	po::variables_map vm;
	po::store(po::command_line_parser(argc, argv).options(all_args).run(), vm);
	po::notify(vm);

	if (vm.count("version"))
	{
		print_version(cerr, *argv, "1.1\n"
			"\tHistory: \n\n"
			"\tv 1.0"
			"16-03-2006\1"
			"First Version\1"
			"More flexible version of diff.\n"
			"\tv 1.1"
			"20-03-2006\1"
			"Added regular expression parameter so that partial matches still work.\n"
			"\tv 1.2"
			"15-07-2008\1"
			"Added case insensitive matches and --to_regex for flexibility.\n"
			"N.B. This code does not have test cases but is hopefully bug free.\n"
					  );
		return false;
	}
	if (vm.count("help"))
	{
		string exe_description =
					"Takes pairs of files and prints out matching lines.\n"
					"Only the first instance of each duplicate will be selected.\n";

		po::options_description visible_args("");
		visible_args.add(mandatory_args).add(args.optional_args).add(advanced_args);
		print_usage(cerr, string(*argv), "--file1in FILE --file2in FILE [OPTIONS]\n",
							visible_args, exe_description, 80);
		return false;
	}
	check_required_options(vm, mandatory_args);
	if (vm.count("debug"))
	{
		args.file_1				= "file1_only.ids";
		args.file_2				= "file2_only.ids";
		args.file_shared		= "shared.ids";
		args.file_merged		= "merged.ids";
	}


	if (!args.regex.length())
	{
		throw std::runtime_error("You have specified an empty regular expression.");
	}
	boost::regex brackets_match_regex("\\(.*\\)");
	if (!boost::regex_search(args.regex, brackets_match_regex, boost::match_default))
		args.regex = '(' + args.regex + ')';

	std::vector<string> file_names;
	file_names.push_back(args.file_1);
	file_names.push_back(args.file_2);
	file_names.push_back(args.file_shared);
	file_names.push_back(args.file_merged);
	file_names.erase(std::remove(file_names.begin(),  file_names.end(), string()), file_names.end());
	sort(file_names.begin(), file_names.end());
	std::vector<string>::iterator i = std::adjacent_find(file_names.begin(),  file_names.end());
	if (i != file_names.end())
	{
		throw std::runtime_error("Output file names must be unique.\nThe file [" + *i 
								 + "] was specified more than once.");
	}
	args.open_err_log();
	return true;
}













